# RUN: llc -march=hexagon -run-pass machine-sink -o - %s | FileCheck %s

# Test that MachineSink does not sink F2_conv_w2sf.
# CHECK: name:{{.*}} main
# CHECK: J2_call @feclearexcept
# CHECK: F2_conv_w2sf
# CHECK: J2_call @fetestexcept
--- |
  target datalayout = "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048"
  target triple = "hexagon"

  @.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1

  ; Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn
  define dso_local i32 @syst_int32_to_float32(i32 %a) local_unnamed_addr #0 {
  entry:
    %conv = sitofp i32 %a to float
    %0 = bitcast float %conv to i32
    ret i32 %0
  }

  ; Function Attrs: argmemonly mustprogress nofree nosync nounwind willreturn
  declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1

  ; Function Attrs: argmemonly mustprogress nofree nosync nounwind willreturn
  declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1

  ; Function Attrs: nounwind
  define dso_local i32 @main() local_unnamed_addr #2 {
  entry:
    %a = alloca i32, align 4
    %b = alloca i32, align 4
    %c = alloca i32, align 4
    %a.0.a.0.a.0.a.0..sroa_cast = bitcast i32* %a to i8*
    call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %a.0.a.0.a.0.a.0..sroa_cast)
    store volatile i32 -16777235, i32* %a, align 4, !tbaa !3
    %b.0.b.0.b.0.b.0..sroa_cast = bitcast i32* %b to i8*
    call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %b.0.b.0.b.0.b.0..sroa_cast)
    store volatile i32 34, i32* %b, align 4, !tbaa !3
    %c.0.c.0.c.0.c.0..sroa_cast = bitcast i32* %c to i8*
    call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %c.0.c.0.c.0.c.0..sroa_cast)
    store volatile i32 34, i32* %c, align 4, !tbaa !3
    %b.0.b.0.b.0.b.0.29 = load volatile i32, i32* %b, align 4, !tbaa !3
    %cmp30 = icmp sgt i32 %b.0.b.0.b.0.b.0.29, 0
    br i1 %cmp30, label %for.body, label %if.end

  for.cond.for.cond.cleanup_crit_edge:              ; preds = %for.body
    %conv.i.le = sitofp i32 %a.0.a.0.a.0.a.0. to float
    %0 = bitcast float %conv.i.le to i32
    %phi.cmp = icmp ugt i32 %0, 100
    br i1 %phi.cmp, label %if.then, label %if.end

  for.body:                                         ; preds = %entry, %for.body
    %i.031 = phi i32 [ %inc4, %for.body ], [ 0, %entry ]
    %c.0.c.0.c.0.c.0. = load volatile i32, i32* %c, align 4, !tbaa !3
    %inc = add nsw i32 %c.0.c.0.c.0.c.0., 1
    store volatile i32 %inc, i32* %c, align 4, !tbaa !3
    %call = tail call i32 @feclearexcept(i32 31) #5
    %a.0.a.0.a.0.a.0. = load volatile i32, i32* %a, align 4, !tbaa !3
    %call2 = tail call i32 @fetestexcept(i32 31) #5
    %call3 = tail call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 %call2) #5
    %inc4 = add nuw nsw i32 %i.031, 1
    %b.0.b.0.b.0.b.0. = load volatile i32, i32* %b, align 4, !tbaa !3
    %cmp = icmp slt i32 %inc4, %b.0.b.0.b.0.b.0.
    br i1 %cmp, label %for.body, label %for.cond.for.cond.cleanup_crit_edge, !llvm.loop !7

  if.then:                                          ; preds = %for.cond.for.cond.cleanup_crit_edge
    %a.0.a.0.a.0.a.0.23 = load volatile i32, i32* %a, align 4, !tbaa !3
    %b.0.b.0.b.0.b.0.20 = load volatile i32, i32* %b, align 4, !tbaa !3
    %add = add nsw i32 %b.0.b.0.b.0.b.0.20, %a.0.a.0.a.0.a.0.23
    %c.0.c.0.c.0.c.0.17 = load volatile i32, i32* %c, align 4, !tbaa !3
    %add7 = add nsw i32 %add, %c.0.c.0.c.0.c.0.17
    br label %cleanup

  if.end:                                           ; preds = %entry, %for.cond.for.cond.cleanup_crit_edge
    %a.0.a.0.a.0.a.0.24 = load volatile i32, i32* %a, align 4, !tbaa !3
    %b.0.b.0.b.0.b.0.21 = load volatile i32, i32* %b, align 4, !tbaa !3
    %mul.neg = mul i32 %b.0.b.0.b.0.b.0.21, -6
    %sub = add i32 %mul.neg, %a.0.a.0.a.0.a.0.24
    %c.0.c.0.c.0.c.0.18 = load volatile i32, i32* %c, align 4, !tbaa !3
    %mul8 = mul nsw i32 %c.0.c.0.c.0.c.0.18, 3
    %add9 = add nsw i32 %sub, %mul8
    br label %cleanup

  cleanup:                                          ; preds = %if.end, %if.then
    %retval.0 = phi i32 [ %add7, %if.then ], [ %add9, %if.end ]
    %1 = bitcast i32* %c to i8*
    %2 = bitcast i32* %b to i8*
    %3 = bitcast i32* %a to i8*
    call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %1)
    call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %2)
    call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %3)
    ret i32 %retval.0
  }

  declare dso_local i32 @feclearexcept(i32) local_unnamed_addr #3

  declare dso_local i32 @fetestexcept(i32) local_unnamed_addr #3

  ; Function Attrs: nofree nounwind
  declare dso_local noundef i32 @printf(i8* nocapture noundef readonly, ...) local_unnamed_addr #4

  attributes #0 = { mustprogress nofree norecurse nosync nounwind readnone willreturn "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="hexagonv68" "target-features"="+v68,-long-calls" }
  attributes #1 = { argmemonly mustprogress nofree nosync nounwind willreturn }
  attributes #2 = { nounwind "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="hexagonv68" "target-features"="+v68,-long-calls" }
  attributes #3 = { "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="hexagonv68" "target-features"="+v68,-long-calls" }
  attributes #4 = { nofree nounwind "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="hexagonv68" "target-features"="+v68,-long-calls" }
  attributes #5 = { nounwind }

  !llvm.module.flags = !{!0, !1}

  !0 = !{i32 1, !"wchar_size", i32 4}
  !1 = !{i32 7, !"frame-pointer", i32 2}
  !3 = !{!4, !4, i64 0}
  !4 = !{!"int", !5, i64 0}
  !5 = !{!"omnipotent char", !6, i64 0}
  !6 = !{!"Simple C/C++ TBAA"}
  !7 = distinct !{!7, !8}
  !8 = !{!"llvm.loop.mustprogress"}

...
---
name:            syst_int32_to_float32
alignment:       16
exposesReturnsTwice: false
legalized:       false
regBankSelected: false
selected:        false
failedISel:      false
tracksRegLiveness: true
hasWinCFI:       false
registers:
  - { id: 0, class: intregs, preferred-register: '' }
  - { id: 1, class: intregs, preferred-register: '' }
liveins:
  - { reg: '$r0', virtual-reg: '%0' }
frameInfo:
  isFrameAddressTaken: false
  isReturnAddressTaken: false
  hasStackMap:     false
  hasPatchPoint:   false
  stackSize:       0
  offsetAdjustment: 0
  maxAlignment:    1
  adjustsStack:    false
  hasCalls:        false
  stackProtector:  ''
  maxCallFrameSize: 4294967295
  cvBytesOfCalleeSavedRegisters: 0
  hasOpaqueSPAdjustment: false
  hasVAStart:      false
  hasMustTailInVarArgFunc: false
  hasTailCall:     false
  localFrameSize:  0
  savePoint:       ''
  restorePoint:    ''
fixedStack:      []
stack:           []
callSites:       []
debugValueSubstitutions: []
constants:       []
machineFunctionInfo: {}
body:             |
  bb.0.entry:
    liveins: $r0

    %0:intregs = COPY $r0
    %1:intregs = F2_conv_w2sf %0, implicit $usr
    $r0 = COPY %1
    PS_jmpret $r31, implicit-def dead $pc, implicit $r0

...
---
name:            main
alignment:       16
exposesReturnsTwice: false
legalized:       false
regBankSelected: false
selected:        false
failedISel:      false
tracksRegLiveness: true
hasWinCFI:       false
registers:
  - { id: 0, class: intregs, preferred-register: '' }
  - { id: 1, class: intregs, preferred-register: '' }
  - { id: 2, class: intregs, preferred-register: '' }
  - { id: 3, class: intregs, preferred-register: '' }
  - { id: 4, class: intregs, preferred-register: '' }
  - { id: 5, class: intregs, preferred-register: '' }
  - { id: 6, class: intregs, preferred-register: '' }
  - { id: 7, class: intregs, preferred-register: '' }
  - { id: 8, class: predregs, preferred-register: '' }
  - { id: 9, class: intregs, preferred-register: '' }
  - { id: 10, class: intregs, preferred-register: '' }
  - { id: 11, class: intregs, preferred-register: '' }
  - { id: 12, class: intregs, preferred-register: '' }
  - { id: 13, class: intregs, preferred-register: '' }
  - { id: 14, class: intregs, preferred-register: '' }
  - { id: 15, class: intregs, preferred-register: '' }
  - { id: 16, class: predregs, preferred-register: '' }
  - { id: 17, class: intregs, preferred-register: '' }
  - { id: 18, class: predregs, preferred-register: '' }
  - { id: 19, class: intregs, preferred-register: '' }
  - { id: 20, class: intregs, preferred-register: '' }
  - { id: 21, class: intregs, preferred-register: '' }
  - { id: 22, class: intregs, preferred-register: '' }
  - { id: 23, class: intregs, preferred-register: '' }
  - { id: 24, class: intregs, preferred-register: '' }
  - { id: 25, class: intregs, preferred-register: '' }
  - { id: 26, class: intregs, preferred-register: '' }
  - { id: 27, class: intregs, preferred-register: '' }
liveins:         []
frameInfo:
  isFrameAddressTaken: false
  isReturnAddressTaken: false
  hasStackMap:     false
  hasPatchPoint:   false
  stackSize:       0
  offsetAdjustment: 0
  maxAlignment:    4
  adjustsStack:    false
  hasCalls:        true
  stackProtector:  ''
  maxCallFrameSize: 4294967295
  cvBytesOfCalleeSavedRegisters: 0
  hasOpaqueSPAdjustment: false
  hasVAStart:      false
  hasMustTailInVarArgFunc: false
  hasTailCall:     false
  localFrameSize:  0
  savePoint:       ''
  restorePoint:    ''
fixedStack:      []
stack:
  - { id: 0, name: a, type: default, offset: 0, size: 4, alignment: 4,
      stack-id: default, callee-saved-register: '', callee-saved-restored: true,
      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
  - { id: 1, name: b, type: default, offset: 0, size: 4, alignment: 4,
      stack-id: default, callee-saved-register: '', callee-saved-restored: true,
      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
  - { id: 2, name: c, type: default, offset: 0, size: 4, alignment: 4,
      stack-id: default, callee-saved-register: '', callee-saved-restored: true,
      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
callSites:       []
debugValueSubstitutions: []
constants:       []
machineFunctionInfo: {}
body:             |
  bb.0.entry:
    successors: %bb.6(0x50000000), %bb.4(0x30000000)

    S4_storeiri_io %stack.0.a, 0, -16777235 :: (volatile store (s32) into %ir.a, !tbaa !3)
    S4_storeiri_io %stack.1.b, 0, 34 :: (volatile store (s32) into %ir.b, !tbaa !3)
    S4_storeiri_io %stack.2.c, 0, 34 :: (volatile store (s32) into %ir.c, !tbaa !3)
    %7:intregs = L2_loadri_io %stack.1.b, 0 :: (volatile dereferenceable load (s32) from %ir.b, !tbaa !3)
    %8:predregs = C2_cmpgti %7, 0
    %6:intregs = A2_tfrsi 0
    J2_jumpf %8, %bb.4, implicit-def $pc

  bb.6:
    successors: %bb.2(0x80000000)

    %9:intregs = A2_tfrsi 31
    %13:intregs = A2_tfrsi @.str
    J2_jump %bb.2, implicit-def $pc

  bb.1.for.cond.for.cond.cleanup_crit_edge:
    successors: %bb.4(0x40000000)

    J2_jump %bb.4, implicit-def dead $pc

  bb.2.for.body:
    successors: %bb.2(0x7c000000), %bb.1(0x04000000)

    %0:intregs = PHI %6, %bb.6, %2, %bb.2
    L4_iadd_memopw_io %stack.2.c, 0, 1 :: (volatile store (s32) into %ir.c, !tbaa !3), (volatile dereferenceable load (s32) from %ir.c, !tbaa !3)
    ADJCALLSTACKDOWN 0, 0, implicit-def $r29, implicit-def dead $r30, implicit $r31, implicit $r30, implicit $r29
    $r0 = COPY %9
    J2_call @feclearexcept, hexagoncsr, implicit-def dead $pc, implicit-def dead $r31, implicit $r29, implicit $r0, implicit-def $r29, implicit-def $r0
    ADJCALLSTACKUP 0, 0, implicit-def dead $r29, implicit-def dead $r30, implicit-def dead $r31, implicit $r29
    %1:intregs = L2_loadri_io %stack.0.a, 0 :: (volatile dereferenceable load (s32) from %ir.a, !tbaa !3)
    ADJCALLSTACKDOWN 0, 0, implicit-def $r29, implicit-def dead $r30, implicit $r31, implicit $r30, implicit $r29
    %17:intregs = F2_conv_w2sf %1, implicit $usr
    $r0 = COPY %9
    J2_call @fetestexcept, hexagoncsr, implicit-def dead $pc, implicit-def dead $r31, implicit $r29, implicit $r0, implicit-def $r29, implicit-def $r0
    ADJCALLSTACKUP 0, 0, implicit-def dead $r29, implicit-def dead $r30, implicit-def dead $r31, implicit $r29
    %11:intregs = COPY $r0
    %12:intregs = COPY $r29
    S2_storeri_io %12, 0, %11 :: (store (s32) into stack)
    ADJCALLSTACKDOWN 4, 0, implicit-def $r29, implicit-def dead $r30, implicit $r31, implicit $r30, implicit $r29
    $r0 = COPY %13
    J2_call @printf, hexagoncsr, implicit-def dead $pc, implicit-def dead $r31, implicit $r29, implicit $r0, implicit-def $r29, implicit-def $r0
    ADJCALLSTACKUP 4, 0, implicit-def dead $r29, implicit-def dead $r30, implicit-def dead $r31, implicit $r29
    %2:intregs = nuw nsw A2_addi %0, 1
    %15:intregs = L2_loadri_io %stack.1.b, 0 :: (volatile dereferenceable load (s32) from %ir.b, !tbaa !3)
    %16:predregs = C2_cmpgt %15, %2
    J2_jumpt %16, %bb.2, implicit-def dead $pc
    J2_jump %bb.1, implicit-def dead $pc

  bb.3.if.then:
    successors: %bb.5(0x80000000)

    %18:predregs = C2_cmpgtui %17, 100
    %24:intregs = L2_loadri_io %stack.0.a, 0 :: (volatile dereferenceable load (s32) from %ir.a, !tbaa !3)
    %25:intregs = L2_loadri_io %stack.1.b, 0 :: (volatile dereferenceable load (s32) from %ir.b, !tbaa !3)
    %26:intregs = L2_loadri_io %stack.2.c, 0 :: (volatile dereferenceable load (s32) from %ir.c, !tbaa !3)
    %3:intregs = nsw M2_acci %26, %25, %24
    J2_jumpf %18, %bb.5, implicit-def dead $pc
    J2_jump %bb.5, implicit-def dead $pc

  bb.4.if.end:
    successors: %bb.5(0x80000000)

    %19:intregs = L2_loadri_io %stack.0.a, 0 :: (volatile dereferenceable load (s32) from %ir.a, !tbaa !3)
    %20:intregs = L2_loadri_io %stack.1.b, 0 :: (volatile dereferenceable load (s32) from %ir.b, !tbaa !3)
    %27:intregs = M2_macsin %19, %20, 6
    %23:intregs = L2_loadri_io %stack.2.c, 0 :: (volatile dereferenceable load (s32) from %ir.c, !tbaa !3)
    %4:intregs = nsw M2_macsip %27, %23, 3

  bb.5.cleanup:
    %5:intregs = PHI %4, %bb.4, %3, %bb.3
    $r0 = COPY %5
    PS_jmpret $r31, implicit-def dead $pc, implicit $r0

...
